﻿using Core;
using FairyGUI;
using System;
using UnityEngine;

public class ListAdapter<T> : IObject, IUpdate where T : GObject
{
    public delegate void ClickEvent(int index, T component);
    public delegate void LongPressEvent(int index, T component);
    public delegate void TouchEvent(int index, T component, InputEvent inputEvent);

    private GList list;
    private TouchEvent onTouchBegin;
    private TouchEvent onTouchMove;
    private TouchEvent onTouchEnd;
    private ClickEvent onClick;
    private LongPressEvent longPressEvent;
    private bool isPress = false;
    private bool isTouchBegin = false;
    private float pressTime = 0;
    private float longPressTime;
    private T longPressComponent;
    private InputEvent longPressInputEvent;

    bool IObject.IsDisposed { get=> longPressEvent == null; }

    public ListAdapter(GList list)
    {
        this.list = list;
    }

    public void SetItemRenderer(Action<int, T> func)
    {
        list.itemRenderer = (index, component) => 
        {
            component.onTouchBegin.Set(OnTouchBegin);
            component.onTouchMove.Set(OnTouchMove);
            component.onTouchEnd.Set(OnTouchEnd);
            component.onClick.Set(OnClick);
            
            func(index, component as T);
        };
    }

    public void UpdateCount(int num)
    {
        list.numItems = num;
    }

    public void UpdateIndex(int index)
    {
        if (index >= 0 && index < list.numItems)
        {
            list.itemRenderer?.Invoke(index, list.GetChildAt(index));
        }
    }

    public void SetTouchBegin(TouchEvent func)
    {
        this.onTouchBegin = func;
    }

    public void SetTouchMove(TouchEvent func)
    {
        this.onTouchMove = func;
    }

    public void SetTouchEnd(TouchEvent func)
    {
        this.onTouchEnd = func;
    }

    public void SetClick(ClickEvent func)
    {
        this.onClick = func;
    }

    public void SetLongPress(LongPressEvent func, float time = 0.3f)
    {
        this.longPressTime = time;
        this.longPressEvent = func;
        if(func != null)
        {
            World.Main.EventSystem.RegisterSystem(this);
        }
    }

    public T GetChild(int index)
    {
        return list.GetChildAt(index) as T;
    }

    private void OnTouchBegin(EventContext context)
    {
        context.CaptureTouch();
        var sender = context.sender as T;
        if (longPressEvent == null)
        {
            onTouchBegin?.Invoke(list.GetChildIndex(sender), sender, context.inputEvent);
        }
        else
        {
            isPress = true;
            isTouchBegin = false;
            longPressComponent = sender;
            longPressInputEvent = context.inputEvent;
        }
    }
    private void OnTouchMove(EventContext context)
    {
        var sender = context.sender as T;
        if(pressTime < longPressTime)
        {
            pressTime = 0;
        }
        onTouchMove?.Invoke(list.GetChildIndex(sender), sender, context.inputEvent);
    }
    private void OnTouchEnd(EventContext context)
    {
        var sender = context.sender as T;

        if (isPress)
        {
            if(pressTime >= longPressTime)
            {
                longPressEvent?.Invoke(list.GetChildIndex(longPressComponent), longPressComponent);
            }

            isPress = false;
            pressTime = 0;
        }

        onTouchEnd?.Invoke(list.GetChildIndex(sender), sender, context.inputEvent);
    }
    private void OnClick(EventContext context)
    {
        var sender = context.sender as T;
        onClick?.Invoke(list.GetChildIndex(sender), sender);
    }

    void IUpdate.Update()
    {
        if (isPress)
        {
            pressTime += Time.deltaTime;
            if(pressTime  >= longPressTime)
            {
                if(!isTouchBegin)
                {
                    Stage.inst.CancelClick(longPressInputEvent.touchId);
                    onTouchBegin?.Invoke(list.GetChildIndex(longPressComponent), longPressComponent, longPressInputEvent);
                    isTouchBegin = true;
                }
                longPressEvent?.Invoke(list.GetChildIndex(longPressComponent), longPressComponent);
            }
        }
    }
}
